package com.piece.mall.controller;

import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.data.Pictures;
import com.piece.core.framework.annotation.permission.AclPermission;
import com.piece.core.framework.annotation.permission.SubmitPermission;
import com.piece.core.framework.constant.ExceptionConstants;
import com.piece.core.framework.exception.ErrorCode;
import com.piece.core.framework.support.bootstrap.DataTable;
import com.piece.core.framework.support.bootstrap.QueryTable;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.support.convert.NumberConvert;
import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.basic.I18nUtil;
import com.piece.core.framework.util.collection.MapUtil;
import com.piece.core.framework.util.file.FileUtil;
import com.piece.core.framework.util.net.IpUtil;
import com.piece.core.framework.util.object.BeanUtil;
import com.piece.core.framework.util.object.ObjectUtil;
import com.piece.core.framework.util.string.QrcodeUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.framework.util.time.DateUtil;
import com.piece.core.pay.client.PayClient;
import com.piece.core.pay.client.PayClientFactory;
import com.piece.core.pay.dto.PayOrderNotifyRespDTO;
import com.piece.core.pay.dto.PayOrderUnifiedReqDTO;
import com.piece.core.web.controller.FrameWorkController;
import com.piece.file.client.FileClientFactory;
import com.piece.file.model.TbSysFile;
import com.piece.file.service.TbSysFileService;
import com.piece.mall.model.OmsOrder;
import com.piece.mall.model.OmsOrderItem;
import com.piece.mall.model.PmsSkuInfo;
import com.piece.mall.model.PmsSpuInfo;
import com.piece.mall.service.*;
import com.piece.mall.vo.OrderDetailVo;
import com.piece.mall.vo.OrderSubmitVo;
import com.piece.module.file.util.word.WordUtil;
import com.piece.module.file.util.word.XWPFPicture;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.*;
import java.util.*;

@Slf4j
@RestController
@Api(tags = {"订单管理"})
@RequestMapping("/api/mall/order")
public class OmsOrderController extends FrameWorkController {

    @Resource
    private OmsOrderService omsOrderService;

    @Resource
    private OmsOrderItemService omsOrderItemService;

    @Resource
    private PmsSpuInfoService pmsSpuInfoService;

    @Resource
    private PmsSkuInfoService pmsSkuInfoService;

    @Resource
    private PaymentService paymentService;

    @Resource
    private TbSysFileService tbSysFileService;

    @Autowired
    private FileClientFactory fileClientFactory;

    @Resource
    private PayClientFactory payClientFactory;

    @PostMapping("/list")
    @AclPermission(code = "mall:order:view")
    @ApiOperation(value = "查询订单列表")
    @ApiImplicitParam(value = "查询条件", dataTypeClass = QueryTable.class, type = "body")
    public List list() {
        QueryTable queryTable = initTable();
        DataTable dataTable = omsOrderService.findPage(queryTable);
        return dataTable.getData();
    }

    @PostMapping("/table")
    @AclPermission(code = "mall:order:view")
    @ApiOperation(value = "查询订单分页数据")
    @ApiImplicitParam(value = "查询条件", dataTypeClass = QueryTable.class, type = "body")
    public AjaxResponse table() {
        QueryTable queryTable = initTable();
        DataTable dataTable = omsOrderService.findPage(queryTable);
        return success(dataTable);
    }

    @GetMapping("/load")
    @AclPermission(code = "mall:order:view")
    @ApiOperation(value = "加载订单表单数据")
    @ApiImplicitParam(name="id", value = "主键")
    public AjaxResponse load() {
        long id = Convert.toLong(getRequest().getParameter("id"), 0L);
        OrderDetailVo orderDetail = omsOrderService.orderDetail(id);
        return success(orderDetail);
    }

    @SubmitPermission
    @PostMapping("/delete/{id}")
    @AclPermission(code = "mall:order:delete")
    @ApiOperation(value = "删除订单数据")
    @ApiImplicitParam(name = "id", value = "主键", type = "path")
    public AjaxResponse delete(@PathVariable Long id) throws Exception {
        omsOrderService.delete(id);
        return success(I18nUtil.message(ExceptionConstants.DELETE_SUCCESS), null);
    }

    @RequestMapping("/donate")
    @ApiOperation(value = "获取捐赠服务信息")
    public AjaxResponse donate() {
        try {
            PmsSpuInfo spuInfo = pmsSpuInfoService.findOneByCondition(MapUtil.builder(new HashMap<String, Object>())
                    .put("Q_spuName_S_EQ", "虚拟交易 - 系统捐赠服务").build());
            List<PmsSkuInfo> skuInfos = pmsSkuInfoService.findBySpu(spuInfo.getId());
            OrderSubmitVo orderSubmit = omsOrderService.convertOrderSubmit(skuInfos, "Piece捐赠服务",
                    "感谢对Piece开源项目的支持", spuInfo.getSpuDescription());
            return success(orderSubmit);
        } catch (Exception e) {
            return AjaxResponse.error(e.getMessage());
        }
    }

    @SubmitPermission
    @RequestMapping("/confirm")
    @ApiOperation(value = "确认订单")
    @ApiImplicitParam(name="skuIds", value = "sku主键")
    public AjaxResponse confirm() {
        try {
            String skuIds = Convert.toStr(getRequest().getParameter("skuIds"), null);
            if (StringUtil.isNotEmpty(skuIds)) {
                List<PmsSkuInfo> skuInfos = pmsSkuInfoService.findByIds(Convert.toLongList(skuIds));
                OrderSubmitVo orderSubmit = omsOrderService.convertOrderSubmit(skuInfos, "Piece商城支付订单",
                        "感谢对Piece开源项目的支持", "");
                return success(orderSubmit);
            }
            return AjaxResponse.result(new ErrorCode(ExceptionConstants.NOT_FOUND, "商品"), null);
        } catch (Exception e) {
            return AjaxResponse.error(e.getMessage());
        }
    }

    @SubmitPermission
    @PostMapping("/submit")
    @ApiOperation(value = "创建订单并支付")
    public AjaxResponse orderSubmit(@RequestBody OrderSubmitVo submit) {
        try {
            OmsOrder order = omsOrderService.submitOrder(submit);
            String ip = IpUtil.getIp(getRequest(), true);
            PayOrderUnifiedReqDTO payOrder = omsOrderService.buildPayOrderUnified(order, ip, submit.getSubject(), submit.getBody());
            return paymentService.payoff(submit.getPayChannel(), submit.getChannelCode(), payOrder);
        } catch (Exception e) {
            return AjaxResponse.error(e.getMessage());
        }
    }

    @SubmitPermission
    @RequestMapping("/check/{orderSn}")
    @ApiOperation(value = "检查订单支付情况")
    @ApiImplicitParam(name = "orderSn", value = "订单编号", type = "path")
    public AjaxResponse check(@PathVariable String orderSn) {
        try {
            OmsOrder order = omsOrderService.findByOrderSn(orderSn);
            PayClient payClient = payClientFactory.getPayClient(order.getPayType(), order.getChannelCode());
            PayOrderNotifyRespDTO payResult = payClient.tradeUnifiedQuery(order.getOrderSn());
            if ("TRADE_SUCCESS".equals(payResult.getTradeStatus())) {
                paymentService.paySuccess(payResult, order.getPayType(), order.getChannelCode());
                return success();
            } else {
                return error(payResult.getData());
            }
        } catch (Exception e) {
            return error(e.getMessage());
        }
    }

    @SubmitPermission
    @PostMapping("/voice/{id}")
    @AclPermission(code = "mall:order:view")
    @ApiOperation(value = "下载电子发票")
    @ApiImplicitParam(name = "id", value = "主键", type = "path")
    public AjaxResponse generateVoice(@PathVariable Long id) {
        OmsOrder order = omsOrderService.findById(id);
        if (null == order) {
            return error(I18nUtil.message(ExceptionConstants.NOT_EXIST), "订单号");
        }

        if (!"3".equals(order.getStatus()) || !"1".equals(order.getBillType())) {
            return error(I18nUtil.message(ExceptionConstants.IS_DISABLE), "订单号");
        }

        InputStream is = null;
        ByteArrayOutputStream os = null;

        try {
            Map<String, Object> data = new HashMap<>();
            List<String> tableItem = null;
            BeanUtil.beanToMap(order, data);
            data.put("createTime", DateUtil.formatDate(new Date(), "yyyy年MM月dd"));
            data.put("amountCn", NumberConvert.digitUppercase(order.getPayAmount().toString()));
            data.put("amountEn", order.getPayAmount().toString());

            List<OmsOrderItem> items = omsOrderItemService.findByCondition(MapUtil.builder(new HashMap<String, Object>())
                    .put("orderSn", order.getOrderSn()).build());
            if (ObjectUtil.isNotEmpty(items)) {
                tableItem = new ArrayList<>();
                data.put("items", items);
                tableItem.add("items");
            }

            TbSysFile template = tbSysFileService.findFileByTableTemplate("voice_template");
            if (null != template) {
                is = fileClientFactory.get().downloadFile(template);
            } else {
                is = FileUtil.readSystemFile("static/template/voice_template.docx");
            }

            File localFile = null;
            String tempPath = FileUtil.getTempPath() + File.separator + "voice" + File.separator + order.getOrderSn() + ".docx";
            try {
                localFile = new File(tempPath);
                if (localFile.exists()) {
                    localFile.delete();
                }
                localFile.createNewFile();
            } catch (Exception e) {
            }

            String utn = getRequestPrefix() + "/piece-admin/public/file/download?path=" + tempPath;
            data.put("utn", Pictures.ofBytes(QrcodeUtil.encode(utn, 132, 132), PictureType.PNG).create());

            os = new ByteArrayOutputStream();
            WordUtil.generateByInputStream(is, data, tableItem, os);
            FileUtil.writeByteArrayToFile(localFile, os.toByteArray());
            os.close();
            os = null;

            Map<String, XWPFPicture> seals = new HashMap<>();
            seals.put("税收入统", XWPFPicture.builder()
                    .inputStream(FileUtil.readSystemFile("static/image/city_manage_seal.png"))
                    .filename("city_manage_seal")
                    .type(PictureType.PNG)
                    .width(75)
                    .height(75)
                    .offsetWidth(280)
                    .offsetHeight(10)
                    .build());
            seals.put("收款单位（章）", XWPFPicture.builder()
                    .inputStream(FileUtil.readSystemFile("static/image/fiscal_bills_seal.png"))
                    .filename("fiscal_bills_seal")
                    .type(PictureType.PNG)
                    .width(90)
                    .height(60)
                    .offsetWidth(70)
                    .offsetHeight(-40)
                    .build());
            os = WordUtil.sealDocument(new FileInputStream(localFile), seals);

            localFile.delete();

            String filename = "voice_" + order.getOrderSn() + ".docx";
            byte[] bytes = os.toByteArray();
            TbSysFile upload = fileClientFactory.get().writeToStore(bytes, "voice", filename, bytes.length);
            return success(upload.getFileId());
        } catch (Exception e) {
            return error(I18nUtil.message(ExceptionConstants.DOWNLOAD_ERROR), e.getMessage());
        } finally {
            try {
                if (null != os) {
                    os.close();
                    os = null;
                }
                if (null != is) {
                    is.close();
                    is = null;
                }
            } catch (IOException e) {}
        }
    }
}
